package com.jerry.boot.core.mvc;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.jerry.boot.core.base.ApiException;
import com.jerry.boot.core.base.JConfigureProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@RestControllerAdvice
@Slf4j
public class JExceptionHandler {

    @Resource
    private MessageSource messageSource;

    @Resource
    private JConfigureProperties jConfigureProperties;

    @ExceptionHandler(value = Exception.class)
    public JsonResult handleException(HttpServletRequest request, Exception e) {
        String requestUri = request.getServletPath();
        log.error("Exception occur on " + requestUri, e);
        JsonResult result = JsonResult.error(500);
        try {
            String rspMsg = messageSource.getMessage(500 + "", null, request.getLocale());
            result.setMsg(rspMsg);
        } catch (NoSuchMessageException ex) {
            result.setMsg("Unknown error");
        }
        dealDebug(e, result);
        return result;
    }

    @ExceptionHandler(value = ApiException.class)
    public JsonResult handleApiException(HttpServletRequest request, ApiException e) {
        String requestUri = request.getServletPath();
        log.error("ApiException occur on " + requestUri, e);
        JsonResult result = JsonResult.error(e.getCode());
        try {
            String rspMsg = messageSource.getMessage(e.getCode() + "", e.getArgs(), request.getLocale());
            result.setMsg(rspMsg);
        } catch (NoSuchMessageException ex) {
            result.setMsg("Unknown error");
        }
        dealDebug(e, result);
        return result;
    }

    protected void dealDebug(Throwable e, JsonResult result) {
        if (jConfigureProperties.isDebug()) {
            result.setDevMsg(ExceptionUtil.stacktraceToString(e));
        }
    }


    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public JsonResult handlerMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
        String requestUri = request.getServletPath();
        log.error("MethodArgumentNotValidException occur on " + requestUri, e);
        JsonResult result = JsonResult.error(502);//缺省值502
        BindingResult bindingResult = e.getBindingResult();
        FieldError fieldError = bindingResult.getFieldError();
        if (fieldError != null) {
            String field = fieldError.getField();
            String rspCode = fieldError.getDefaultMessage();
            String code = fieldError.getCode();
            String rule = null;
            try {
                rule = messageSource.getMessage(code, null, request.getLocale());
            } catch (NoSuchMessageException ex) {
                rule = "unknown";
            }
            rspCode = StrUtil.isBlank(rspCode) ? "501" : rspCode;
            if (ReUtil.isMatch("^[0-9]*$", rspCode)) {
                result.setCode(Integer.parseInt(rspCode));
            }else {
                rspCode = "501";
            }
            try {
                String rspMsg = messageSource.getMessage(rspCode, new String[]{field, rule}, request.getLocale());
                result.setMsg(rspMsg);
            } catch (NoSuchMessageException ex) {
                result.setMsg("param validate fail");
            }
        } else {
            result.setMsg(messageSource.getMessage("502", null, request.getLocale()));
        }
        dealDebug(e, result);
        return result;
    }
}
